package com.riccardocardin.structured.concurrency.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.StructuredTaskScope;

import static com.riccardocardin.structured.concurrency.model.Model.Repository;
import static com.riccardocardin.structured.concurrency.model.Model.UserId;

public class RepositoryServiceCacheImpl implements RepositoryService {

    private static final Logger LOGGER = LoggerFactory.getLogger("GitHubApp");

    private final RepositoryService repositoryService;
    private final RepositoryCache repositoryCache;

    public RepositoryServiceCacheImpl(RepositoryService repositoryService, RepositoryCache repositoryCache) {
        this.repositoryService = repositoryService;
        this.repositoryCache = repositoryCache;
    }

    @Override
    public List<Repository> findRepositories(UserId userId) throws InterruptedException, ExecutionException {
        try (var scope = new StructuredTaskScope.ShutdownOnSuccess<List<Repository>>()) {
            scope.fork(() -> repositoryCache.findRepositories(userId));
            scope.fork(() -> {
                List<Repository> repositories = repositoryService.findRepositories(userId);
                repositoryCache.addToCache(userId, repositories);
                return repositories;
            });
            return scope.join().result(ExecutionException::new);
        }
    }

    // or use the generic Concurrents.raceAll util method
    /*@Override
    public List<Repository> findRepositories(UserId userId) throws InterruptedException, ExecutionException {
        return Concurrents.raceAll(
                () -> repositoryCache.findRepositories(userId),
                () -> {
                    List<Repository> repositories = repositoryService.findRepositories(userId);
                    repositoryCache.addToCache(userId, repositories);
                    return repositories;
                }
        );
    }*/
}
